package com.qianyitian.hope2.analyzer.service;

import com.alibaba.fastjson.JSON;
import com.qianyitian.hope2.analyzer.model.*;
import com.qianyitian.hope2.analyzer.util.AlgorithmUtil;
import com.qianyitian.hope2.analyzer.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class WatchlistService {
    public static final String USER_NAME = "bing";
    public static final String STOCK_STORE_KEY = "-watchlist";
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private StockService favoriteStockService;


    public String getWatchlist() {
        List values = redisTemplate.opsForHash().values(USER_NAME + STOCK_STORE_KEY);
        List<Watch> watchlist = (List<Watch>) values.stream().map(item -> {
            String json = (String) item;
            Watch watch = JSON.parseObject(json, Watch.class);

            Stock stock = favoriteStockService.getStockDailySA(watch.getCode());
            if (stock != null) {
                try {
                    calc(stock, watch);
                } catch (Exception e) {
                    logger.error(stock.getName() + "  watchlist calculation error", e);
                }
            }
            return watch;
        }).collect(Collectors.toList());
        return JSON.toJSONString(watchlist);
    }


    public SymbolList getWatchlistSymbols() {
        SymbolList symbols = new SymbolList();
        List values = redisTemplate.opsForHash().values(USER_NAME + STOCK_STORE_KEY);
        List<Stock> watchlist = (List<Stock>) values.stream().map(item -> {
            String json = (String) item;
            Watch watch = JSON.parseObject(json, Watch.class);
            Stock stock = new Stock();
            stock.setCode(watch.getCode());
            return stock;
        }).collect(Collectors.toList());
        symbols.setSymbols(watchlist);
        return symbols;
    }

    private void calc(Stock stock, Watch watch) {
        watch.setName(stock.getName());
        watch.setUrl(Utils.convert163StockURL(stock.getCode()));
        LocalDateTime watchTime = watch.getTime();
        LocalDate targetDate = toMappingDate(watchTime);
        List<KLineInfo> kList = stock.getkLineInfos();
        if (kList.isEmpty()) {
            logger.error(stock.getName() + " is empty k line for watchlist");
            return;
        }
        LocalDate endDate = kList.get(kList.size() - 1).getDate();
        if (targetDate.isAfter(endDate)) {
            return;
        }

        int targetIndex = -1;
        for (int i = kList.size() - 1; i >= 0; i--) {
            targetIndex = i + 1;
            if (kList.get(i).getDate().compareTo(targetDate) == -1) {
                break;
            }
        }

        double start = kList.get(targetIndex).getClose();
        double end = kList.get(kList.size() - 1).getClose();
        String label = Utils.calcRangeLabel(start, end);
        watch.setRange(label);

        int[] index = AlgorithmUtil.maxAndMinValue(kList, targetIndex);
        double maxValue = kList.get(index[0]).getClose();
        double minValue = kList.get(index[1]).getClose();
        String maxlabel = Utils.calcRangeLabel(start, maxValue);
        String minlabel = Utils.calcRangeLabel(start, minValue);
        watch.setMaxRange(maxlabel);
        watch.setMinRange(minlabel);
    }

    private LocalDate toMappingDate(LocalDateTime watchTime) {
        LocalDateTime toComare = LocalDateTime.of(watchTime.getYear(), watchTime.getMonthValue(), watchTime.getDayOfMonth(), 15, 0, 0);
        if (watchTime.isBefore(toComare)) {
            return watchTime.toLocalDate();
        } else {
            return watchTime.toLocalDate().plusDays(1);
        }
    }

    public void add(String code) {
        Watch watch = new Watch();
        watch.setTime(LocalDateTime.now());
        watch.setCode(code);
        String json = JSON.toJSONString(watch);
        Boolean ok = redisTemplate.opsForHash().putIfAbsent(USER_NAME + STOCK_STORE_KEY, code, json);
    }

    public void delete(String code) {
        redisTemplate.opsForHash().delete(USER_NAME + STOCK_STORE_KEY, code);
    }

    public boolean check(String code) {
        Boolean aBoolean = redisTemplate.opsForHash().hasKey(USER_NAME + STOCK_STORE_KEY, code);
        return aBoolean;
    }
}
